As software systems have become more complex, code modularity has become an increasingly important design goal. Building software systems using modular components enables developers to reuse code, modify software quickly when requirements evolve, mitigate costs of producing multiple versions, and reduce development time by integrating pre-written, third-party components.
Many tools and frameworks have been proposed for facilitating modular software development. For example, Java Enterprise Edition™ (Java EE) is a widely used application server environment for enterprise server programming in Java™. The platform includes a component container that provides a set of services, application programming interfaces (APIs), and protocols that facilitate modular software development. The container also provides runtime support, such as lifecycle management, security frameworks, deployment services, automatic threading, transaction management, and other services. A container that provides such services, such as the Java EE container, may be referred to herein generally as an application server container or component container. The components to which the container provides such services are said to be managed by the container.
Using Java EE standards, developers can define web-tier components (e.g., Servlets), business-tier components (e.g., Enterprise Java Beans™ or EJBs™), components for accessing enterprise information systems (e.g., JDBC™), and others, and assemble applications from these components. At runtime, the assembled application can be deployed on the container as a package of components (e.g., using a JAR). The container provides the application components with services, such as lifecycle management, security, deployment, threading, transaction management, persistence, remote invocation, context propagation, and others. By providing such services, an application server component container, such as that provided by Java EE, enables programmers to concentrate on developing application logic rather than on wiring components together and implementing commonly required and/or low-level functionality.
There has also been much interest in service-oriented architectures and dynamic module systems. A dynamic module system is a framework that allows components to be deployed as independent modules and to dynamically discover and use one another during runtime. Such systems are “dynamic” in that components may enter and/or exit the system independently of other components. For example, OSGi is a module system for building modular, service-oriented Java™ applications. OSGi provides a service registry where developers can register and unregister services. Each service listed by the service registry may have multiple implementations and an OSGi component may query the service registry to discover and retrieve various implementations of a particular service. In response to a service query, an OSGi container may determine an appropriate implementation that satisfies the query and return it to the querying component. Using the handle, the discovering object may then invoke the service. Related services are often deployed in OSGi as a group of implementing classes known as a bundle or module. Such a module may define a set of capabilities (i.e., service interfaces), requirements (i.e., dependencies), and classes (i.e., implementations). OSGi includes a lifecycle layer that enables modules to be dynamically installed, started, stopped, updated, and uninstalled during runtime, which enables reconfiguration without system downtime.